#pragma once

#include "SDL/SDL.h"
#include "spoint.h"
#include "srect.h"
#include "bitmap.h"
#include "pixelfont.h"
#include "graphics_constants.h"	// VSDL_FLIP_* constants

class PixelFont;

/**
 * @param a_filename
 * @return a pointer to an SDL_Surface optimized to the current SDL display format
 */
SDL_Surface *VSDL_loadImage(const char * a_filename);

/**
 * @param a_surface an SDL_Surface to set a transparent color for
 * @param a_transparentRGB example: 0xff00ff for magenta, 0x0000ff for red, (R | G << 8 | B << 16)
 */
void VSDL_setTransparentColor(SDL_Surface * a_surface, 
						 const int & a_transparentRGB);

/**
 * @param a_source the SDL surface (tile bitmap) to treat as the tile source
 * @param a_tileSize an SDL_Rect who's width and height values are the width
 * and height of the tiles in the tile source
 * @param a_index the tile from the tile source to draw, with the upper-left
 * most tile being index 0.
 * @param a_dest what surface to draw the tile to
 * @param a_x
 * @param a_y coordinate to draw the tile to on the destination surface
 */
void VSDL_drawTile(SDL_Surface * a_source, SDL_Rect * a_tileSize, 
			  const int & a_index, SDL_Surface * a_dest, int a_x, int a_y);

/** TODO document me with an explanaition */
PixelFont * VSDL_getDefaultFont();

/**
 * @param a_defaultFontImage source of the pixel font. Note: you must release this yourself
 * @param a_tileSize size of each mono-space character, laid out in a grid
 * @param a_startingLetter what is the first printable letter (0th letter in the source image)
 * @param a_numLetters how many printable letters this pixel font has
 */
void VSDL_setDefaultMonospaceFont(SDL_Surface * a_defaultFontImage, const SPoint & a_defaultFontCharSize,
							 const int & a_firstLetter, const int & a_numLetters);

/**
 * @param a_defaultFontImage source of the pixel font (pixel markers to show glyph size).
 * Note: you must release this yourself SDL_Surface
 * @param a_startingLetter what is the first printable letter (0th letter in the source image)
 * @param a_numLetters how many printable letters this pixel font has
 */
void VSDL_setDefaultVariableWidthFont(SDL_Surface * a_defaultFontImage,
							 const int & a_firstLetter, const int & a_numLetters);

/** TODO document me with an explanaition */
void VSDL_drawString(PixelFont * a_font, char * a_text, SDL_Surface * a_dest, const SPoint & a_point);

/**
 * @param a_text using the defualt pixel font, write this text...
 * @param a_dest on this surface...
 * @param a_point at this location (upper left coordinate of 0th letter)
 */
void VSDL_drawString(char * a_text, SDL_Surface * a_dest, const SPoint & a_point);

/** draws the given rectangle using the given 0xRRGGBB color */
void VSDL_drawRect(SDL_Surface * a_surface, SDL_Rect * a_rect, Uint32 a_rgbColor, 
			  const int & a_borderSize);


#define DRAW_RECT_MINY_SIDE		(1<<0)
#define DRAW_RECT_MAXY_SIDE		(1<<1)
#define DRAW_RECT_MINX_SIDE		(1<<2)
#define DRAW_RECT_MAXX_SIDE		(1<<3)
#define DRAW_RECT_ALL_SIDES		(0xf)
/**
 * draws the given rectangle using the given 0xRRGGBB color
 * @param a_sidesToDraw (DRAW_RECT_MINY_SIDE | DRAW_RECT_MAXY_SIDE | DRAW_RECT_MINX_SIDE | DRAW_RECT_MAXX_SIDE)
 */
void VSDL_drawRect(SDL_Surface * a_surface, SDL_Rect * a_rect, Uint32 a_rgbColor, 
				   const int & a_borderSize, const int & a_sidesToDraw);

extern Uint32 g_DIRTY_RECTANGLE_FILL_COLOR;
//#define VSDL_FillRect(dst, dstrect, color)	SDL_FillRect(dst, dstrect, (++g_DIRTY_RECTANGLE_FILL_COLOR)+color)
#define VSDL_FillRect(dst, dstrect, color)	SDL_FillRect(dst, dstrect, color)

// NOTE: the following methods assume a single-threaded application, where only one screen is being drawn to at a time
/**
 * @param screen to shrink the clip rectangle of
 * @param rectangle that is the narrower clip
 * @return true if the new clip is still valid
 */
bool VSDL_pushClip(SDL_Surface * a_surface, const SRect & a_clipRect);
/** goes back to the previous clip */
void VSDL_popClip(SDL_Surface * a_surface);
SRect VSDL_getClip(SDL_Surface * a_surface);

/**
 * @param a_surface where to draw the broken rectangle
 * @param a_rect what rectangle to draw broken
 * @param a_rgbColor what color to draw the rectangle in
 * @param a_borderSize how many pixels thick to make the lines
 * @param a_break how large a break to make between broken bits
 */
void VSDL_drawRectBroken(SDL_Surface * a_surface, SDL_Rect * a_rect, const RGB_QUAD & a_rgbColor, 
					const int & a_borderSize, const int & a_break);

/**
 * @param a_src an image to flip
 * @param a_flip how to clip the image
 */
SDL_Surface * VSDL_createFlippedSurface(SDL_Surface * a_src, const int & a_flip);

/**
 * @param a_surface an SDL_Surface
 * @param a where on the SDL surface to change the pixel
 * @param pixel the pixel color or index, already formated to work with this given SDL_Surface
 */
void VSDL_setSurfacePixel(SDL_Surface* a_surface, const SPoint & a, const Uint32 & pixel);

/**
 * @param a_surface an SDL_Surface
 * @param a where on the SDL surface to get the pixel
 * @return the pixel color or index formated to work with this given SDL_Surface
 */
Uint32 VSDL_getSurfacePixel(const SDL_Surface * a_surface, const SPoint & a);

/**
 * @param a_dest where to draw the source image to
 * @param a_destLoc where in the destination image to draw the source image
 * @param a_src the image to draw to the destination image
 * @param a_srcRect which part of the source image to draw
 * @param a_flip an SDL_FLIP_* variable to modify how the destination image is drawn
 * @param a_pixelSize how many pixels squared source image should be in destination image
 * TODO needs to be more efficient
 */
void VSDL_drawSurfaceToSurface(SDL_Surface * a_dest, const SPoint & a_destLoc, 
				 SDL_Surface * a_src, SDL_Rect * a_srcRect, const int & flip, 
				 const int & a_pixelSize);

/**
 * @param a_dest where to draw the source image to
 * @param a_destLoc where in the destination image to draw the source image
 * @param bmp the BitMaP image to draw to the destination image
 * @param a_srcRect which part of the source image to draw
 * @param a_flip an SDL_FLIP_* variable to modify how the destination image is drawn
 * @param a_pixelSize how many pixels squared source image should be in destination image
 * TODO needs to be more efficient
 */
void VSDL_drawBitmapToSurface(SDL_Surface * a_dest, const SPoint & a_destLoc, 
				BitMaP * bmp, const SRect & a_srcRect, const int & flip, 
				const int & a_pixelSize, //const RGB_QUAD & a_transparentColor)
				const int & a_transparentColorIndex);

/**
 * @param rgb which RGB_QUAD to convert into an SDL_Surface formatted color
 * @param format the SDL_Surface format to convert this color into
 */
Uint32 RGBQUAD_toSurfaceColor(const RGB_QUAD & rgb, SDL_PixelFormat * format);

/**
 * convert a BitMaP to an SDL_Surface
 * @param a_bmp a BitMaP image to convert to an SDL_Surface
 * @param f the SDL_PixelFormat to use, probably screen->format.
 */
SDL_Surface * VSDL_bitmapToSurface(const BitMaP * a_bmp, SDL_PixelFormat * f);
